namespace Warehouse

open System
open System.Diagnostics
open System.Deployment.Application
open System.Data.SqlClient
open Microsoft.SqlServer.Management.Smo
open FSharp.Windows

type MainController(repository : DataModel.Repository) = 
    inherit Controller<MainEvents, MainModel>()

    static member Mvc(mainWindow)= 
        let repository = new DataModel.Repository()
        let view = MainView(mainWindow)
        Mvc(Model.Create(), view, MainController(repository))
            <+> (InventoryController(repository), InventoryView(view.Control.Inventory), fun m -> m.Catalog)
            <+> (ClientController(repository), ClientView(view.Control.Clients), fun m -> m.Clients)
            <+> (VendorController(repository), VendorView(view.Control.Vendors), fun m -> m.Vendors)
            <+> (InvoiceController(repository), InvoiceView(view.Control.Invoices), fun m -> m.Invoices)
            <+> (ProductSearchChildController(repository), ProductSearchPartialView(view.Control.Inventory.ProductSearch), fun m -> m.Catalog.ProductSearch)
            <+> (PurchaseOrderController(repository), PurchaseOrderView(view.Control.PurchaseOrders), fun m -> m.PurchaseOrders)
            <+> (OfferController(repository), OfferView(view.Control.Offers), fun m -> m.Offers)

    override this.InitModel model = 

        let sqlServer = Server.FromConfigFile()

        model.DatabaseServer <- repository.Connection.DataSource
        model.IsBackUpEnable <- sqlServer.IsLocal
        model.IsRestoreEnable <- sqlServer.IsLocal
        model.PossiblyProductionData <- Debugger.IsAttached && not sqlServer.IsLocal
        if ApplicationDeployment.IsNetworkDeployed
        then 
            model.ProgramVersion <- sprintf "Version: %O" ApplicationDeployment.CurrentDeployment.CurrentVersion

        model.Catalog <- Model.Create()
        model.Clients <- Model.Create()
        model.Vendors <- Model.Create()
        model.Invoices <- Model.Create()
        model.PurchaseOrders <- Model.Create()
        model.Offers <- Model.Create()

    override this.Dispatcher = function
        | Brands -> Sync(ignore >> this.Brands)
        | NewProduct -> Async this.NewProduct
        | NewClient -> Sync this.NewClient
        | NewVendor -> Sync this.NewVendor
        | NewInvoice -> Async this.NewInvoice
        | NewPurchaseOrder -> Async this.NewPurchaseOrder

        | InvoicesReport -> Sync this.InvoicesReport
        | PurchaseOrdersReport -> Sync this.PurchaseOrdersReport
        | CatalogReport -> Sync this.CatalogReport

        | CompanyInfo -> Sync(ignore >> this.CompanyInfo)

        | BackupDatabase -> Sync(ignore >> this.BackupDatabase)
        | RestoreDatabase -> Sync(ignore >> this.RestoreDatabase)

    member this.Brands() = 
        let view = BrandView()
        let controller = BrandController repository
        let model = Model.Create();
        let mvc = Mvc(model, view, controller)
        mvc.StartDialog() |> ignore
        
    member this.NewProduct model = 
        async {
            let view = ProductView()
            let controller = ProductController repository
            let! result = Mvc.startWindow(view, controller)
            result |> Option.iter (fun product ->
                model.Catalog.ProductSearch.Products.Add product
                model.Catalog.ProductSearch.SelectedProduct <- product
            )
        }

    member this.NewClient model = 
        let view = ClientDetailsView()
        let controller = ClientDetailsController repository
        (view, controller)
        |> Mvc.startDialog
        |> Option.iter model.Clients.Items.Add
        
    member this.NewVendor model = 
        let view = VendorDetailsView()
        let controller = VendorDetailsController repository
        Mvc.startDialog(view, controller) 
        |> Option.iter model.Vendors.Items.Add

    member this.NewInvoice model = 
        async {
            let view = InvoiceDetailsView()
            let controller = InvoiceDetailsController repository
            let! invoice = Mvc.startWindow(view, controller)
            invoice |> Option.iter model.Invoices.Items.Add 
        }
        
    member this.NewPurchaseOrder model = 
        async {
            let view = PurchaseOrderDetailsView()
            let controller = PurchaseOrderDetailsController(repository)
            let! invoice = Mvc.startWindow(view, controller)
            invoice |> Option.iter model.PurchaseOrders.Items.Add 
        }

    member this.InvoicesReport model = 
        let view = InvoicesAndPOsReport.ReporView()
        let controller = InvoicesAndPOsReport.ClientInvoicesController repository
        Mvc.startDialog(view, controller)
        |> Option.iter(fun model ->
            ReportForm.ShowReportDialog(
                reportName = "ClientInvoices", 
                parameters = [
                    "client", string model.SelectedCompany
                    "from", model.From.ToString("yyyy-MM-dd")
                    "to", model.To.ToString("yyyy-MM-dd")
                ]
            )
        )

    member this.PurchaseOrdersReport model = 
        let view = InvoicesAndPOsReport.ReporView()
        let controller = InvoicesAndPOsReport.VendorPOsController repository
        Mvc.startDialog(view, controller)
        |> Option.iter(fun model ->
            ReportForm.ShowReportDialog(
                reportName = "VendorPOs", 
                parameters = [
                    "vendor", string model.SelectedCompany
                    "from", model.From.ToString("yyyy-MM-dd")
                    "to", model.To.ToString("yyyy-MM-dd")
                ]
            )
        )

    member this.CatalogReport model = 
        let view = CatalogReporView()
        let controller = CatalogReportController repository
        Mvc.startDialog(view, controller) |> ignore

    member this.CompanyInfo() = 
        let view = CompanyInfoView()
        let controller = CompanyInfoController repository
        let model = EntityModel.Load repository.CompanyInfo
        Mvc.startDialog(view, controller) |> ignore

    member this.BackupDatabase() = 
        let view = DatabaseMaintenanceView()
        let controller = BackUpController repository
        Mvc.startDialog(view, controller) |> ignore

    member this.RestoreDatabase() = 
        let view = DatabaseMaintenanceView()
        let controller = RestoreController repository
        Mvc.startDialog(view, controller) |> ignore
        
        
